package com.ylr.blog.framework.service.impl;

import com.ylr.base.common.constant.Constant;
import com.ylr.blog.common.dto.blog_space.BlogSpaceDto;
import com.ylr.base.common.enums.CommonEnum;
import com.ylr.base.common.enums.ResultEnum;
import com.ylr.base.common.exception.YlrException;
import com.ylr.base.common.po.user.UserPo;
import com.ylr.blog.common.vo.blog_space.BlogSpaceVo;
import com.ylr.blog.framework.service.BlogService;
import com.ylr.blog.framework.service.BlogSpaceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.ylr.blog.common.enums.BlogResultEnum;
import com.ylr.base.common.utils.UserUtils;
import com.ylr.base.framework.service.SnowflakeService;
import lombok.AllArgsConstructor;
import org.springframework.stereotype.Service;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

import com.ylr.blog.framework.mapper.BlogSpaceMapper;
import com.ylr.blog.framework.entity.BlogSpaceEntity;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-05-18 21:39:53
 * className: BlogSpaceServiceImpl
 * version: 1.0
 * description:
 */
@Service("blogSpaceService")
@AllArgsConstructor
public class BlogSpaceServiceImpl extends ServiceImpl<BlogSpaceMapper, BlogSpaceEntity> implements BlogSpaceService {

    private static final Logger log = LoggerFactory.getLogger(BlogSpaceServiceImpl.class);

    private final BlogService blogService;

    private final SnowflakeService snowflakeService;

    @Override
    public void saveBlogSpace(BlogSpaceVo blogSpaceVo) {
        // 获取正在保存博客空间的用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        BlogSpaceEntity blogSpace = this.getNewBlogSpace(blogSpaceVo, userPo, date);

        // 保存用户博客空间
        baseMapper.insert(blogSpace);
        log.info("保存用户博客空间完成");
    }

    @Override
    public void addBlogSpace(Long userId, String name) {
        Date date = new Date();

        BlogSpaceEntity blogSpace = this.newBlogSpace(userId, name, date);

        // 保存用户博客空间
        baseMapper.insert(blogSpace);
        log.info("添加用户博客空间完成");
    }

    @Override
    public List<BlogSpaceDto> getBlogSpaceList() {
        // 获取请求用户
        UserPo userPo = UserUtils.getUser();

        LambdaQueryWrapper<BlogSpaceEntity> blogSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        blogSpaceLambdaQueryWrapper.select(BlogSpaceEntity::getId, BlogSpaceEntity::getName);
        // 匹配条件
        blogSpaceLambdaQueryWrapper.eq(BlogSpaceEntity::getUserId, userPo.getId())
                .eq(BlogSpaceEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 排序
        blogSpaceLambdaQueryWrapper.orderByDesc(BlogSpaceEntity::getId);
        // 查询数据
        List<BlogSpaceEntity> blogSpaceList = baseMapper.selectList(blogSpaceLambdaQueryWrapper);

        // 数据封装
        List<BlogSpaceDto> blogSpaceDtoList = new ArrayList<>(blogSpaceList.size());
        for (BlogSpaceEntity blogSpace : blogSpaceList) {
            BlogSpaceDto blogSpaceDto = this.getBlogSpaceDto(blogSpace);
            blogSpaceDtoList.add(blogSpaceDto);
        }
        return blogSpaceDtoList;
    }

    @Override
    public BlogSpaceDto getBlogSpace(Long id) {
        BlogSpaceEntity blogSpace = this.findBlogSpace(id);
        // 数据封装
        return this.getBlogSpaceDto(blogSpace);

    }

    @Override
    public Integer getNextSort(Long parentId) {
        // 获取请求用户
        Long optUserId = UserUtils.getUserId();

        Integer maxSort = baseMapper.selectMaxSort(parentId, optUserId, CommonEnum.DELETE_NO.getValue());
        if (Objects.isNull(maxSort)) {
            maxSort = 0;
        }
        return maxSort + 1;
    }

    @Transactional
    @Override
    public void updateBlogSpace(BlogSpaceVo blogSpaceVo) {
        // 获取请求用户
        UserPo userPo = UserUtils.getUser();
        Date date = new Date();

        boolean updateParent = false;

        // 查询数据
        BlogSpaceEntity blogSpace = this.findBlogSpace(blogSpaceVo.getId());

        BlogSpaceEntity _blogSpace = new BlogSpaceEntity();
        _blogSpace.setId(blogSpaceVo.getId())
                .setUserId(userPo.getId())
                .setName(blogSpaceVo.getName())
                .setSort(blogSpaceVo.getSort())
                .setUpdateTime(date);
        if (!blogSpaceVo.getParentId().equals(blogSpace.getParentId())) {
            // 切换父级空间
            _blogSpace.setParentId(blogSpaceVo.getParentId())
                    .setParentPath(blogSpaceVo.getParentPath() + blogSpaceVo.getId() + Constant.SPLIT);

            updateParent = true;
        }
        // 修改数据
        baseMapper.updateById(_blogSpace);
        log.info("修改用户博客空间完成");

        if (updateParent) {
            // 获取用户博客子空间列表
            List<BlogSpaceEntity> blogSpaceChildrenList = this.getChildrenList(userPo.getId(), blogSpace.getParentPath());
            if (blogSpaceChildrenList.isEmpty()) {
                log.info("用户博客子空间为空");
                return;
            }
            List<BlogSpaceEntity> blogSpaceList = new ArrayList<>();
            for (BlogSpaceEntity blogSpaceEntity : blogSpaceChildrenList) {
                String parentPath = blogSpaceEntity.getParentPath();
                // 父级路径替换
                parentPath = parentPath.replaceFirst(blogSpace.getParentPath(), _blogSpace.getParentPath());

                BlogSpaceEntity updateBlogSpace = new BlogSpaceEntity();
                updateBlogSpace.setId(blogSpaceEntity.getId())
                        .setUserId(userPo.getId())
                        .setParentPath(parentPath)
                        .setUpdateTime(date);
                // 记录
                blogSpaceList.add(updateBlogSpace);
            }
            // 批量更新
            this.updateBatchById(blogSpaceList);
        }
    }

    @Override
    public void deleteBlogSpace(Long id) {
        // 获取请求对象
        UserPo userPo = UserUtils.getUser();

        // 1、获取子空间个数 并进行判断
        Integer num = baseMapper.selectChildrenCount(id, userPo.getId(), CommonEnum.DELETE_NO.getValue());
        if (Objects.isNull(num)) {
            num = 0;
        }
        if (num != 0) {
            log.info("待删除用户博客空间含有子空间数据，不能进行删除");
            throw new YlrException(BlogResultEnum.DELETE_BLOG_SPACE_FAIL);
        }

        // 2、获取空间关联博客数量
        num = blogService.getBlogNum(userPo.getId(), id);
        if (Objects.isNull(num)) {
            num = 0;
        }
        if (num != 0) {
            log.info("待删除用户博客空间关联的博客数量不为空，不能进行删除");
            throw new YlrException(BlogResultEnum.DELETE_BLOG_SPACE_FAIL2);
        }

        // 3、删除用户博客空间
        LambdaUpdateWrapper<BlogSpaceEntity> blogSpaceLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
        // 设置字段值
        blogSpaceLambdaUpdateWrapper.set(BlogSpaceEntity::getDeleteStatus, CommonEnum.DELETE_YES.getValue())
                .set(BlogSpaceEntity::getUpdateTime, new Date());
        // 匹配条件
        blogSpaceLambdaUpdateWrapper.eq(BlogSpaceEntity::getId, id)
                .eq(BlogSpaceEntity::getUserId, userPo.getId())
                .eq(BlogSpaceEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 更新数据
        int count = baseMapper.update(null, blogSpaceLambdaUpdateWrapper);
        log.info("删除用户博客空间完成。count={}", count);
        if (count == 0) {
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
    }

    /**
     * 查询用户博客空间
     * @param id 主键
     * @return 用户博客空间对象
     */
    private BlogSpaceEntity findBlogSpace(Long id) {
        // 获取请求用户
        UserPo userPo = UserUtils.getUser();

        LambdaQueryWrapper<BlogSpaceEntity> blogSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        blogSpaceLambdaQueryWrapper.select(BlogSpaceEntity::getId, BlogSpaceEntity::getParentId, BlogSpaceEntity::getParentPath,
                BlogSpaceEntity::getName, BlogSpaceEntity::getSort, BlogSpaceEntity::getStatus);
        // 匹配条件
        blogSpaceLambdaQueryWrapper.eq(BlogSpaceEntity::getId, id)
                .eq(BlogSpaceEntity::getUserId, userPo.getId())
                .eq(BlogSpaceEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        List<BlogSpaceEntity> blogSpaceList = baseMapper.selectList(blogSpaceLambdaQueryWrapper);
        if (blogSpaceList.isEmpty()) {
            log.info("用户博客空间不存在");
            throw new YlrException(ResultEnum.NOT_FOUND);
        }
        return blogSpaceList.get(0);
    }

    /**
     * 用户博客空间参数对象转化成用户博客空间实体对象
     * @param blogSpaceVo 用户博客空间参数对象
     * @param userPo      操作用户对象
     * @param date        操作日期对象
     * @return 用户博客空间实体对象
     */
    private BlogSpaceEntity getNewBlogSpace(BlogSpaceVo blogSpaceVo, UserPo userPo, Date date) {
        BlogSpaceEntity blogSpace = new BlogSpaceEntity();
        blogSpace.setId(snowflakeService.getId())
                .setParentId(blogSpaceVo.getParentId())
                .setParentPath(blogSpaceVo.getParentPath() + blogSpace.getId() + Constant.SPLIT)
                .setUserId(userPo.getId())
                .setName(blogSpaceVo.getName())
                .setSort(blogSpaceVo.getSort())
                .setStatus(CommonEnum.STATUS_USE.getValue())
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setUpdateTime(date)
                .setCreateTime(date);
        return blogSpace;
    }

    /**
     * 生成用户博客空间实体对象
     * @param userId 用户主键
     * @param name   空间名称
     * @return 用户博客空间实体对象
     */
    private BlogSpaceEntity newBlogSpace(Long userId, String name, Date date) {
        BlogSpaceEntity blogSpace = new BlogSpaceEntity();
        blogSpace.setId(snowflakeService.getId())
                .setParentId(CommonEnum.DEFAULT_ID.getLongValue())
                .setParentPath(blogSpace.getId() + Constant.SPLIT)
                .setUserId(userId)
                .setName(name)
                .setSort(Constant.ZERO)
                .setStatus(CommonEnum.STATUS_USE.getValue())
                .setDeleteStatus(CommonEnum.DELETE_NO.getValue())
                .setUpdateTime(date)
                .setCreateTime(date);
        return blogSpace;
    }

    /**
     * 用户博客空间封装
     * @param blogSpace 用户博客空间对象
     * @return 封装结果
     */
    private BlogSpaceDto getBlogSpaceDto(BlogSpaceEntity blogSpace) {
        BlogSpaceDto blogSpaceDto = new BlogSpaceDto();
        blogSpaceDto.setId(Optional.ofNullable(blogSpace.getId()).map(Objects::toString).orElse(null))
                .setParentId(Optional.ofNullable(blogSpace.getParentId()).map(Objects::toString).orElse(null))
                .setParentPath(blogSpace.getParentPath())
                .setName(blogSpace.getName())
                .setSort(blogSpace.getSort())
                .setStatus(blogSpace.getStatus());
        return blogSpaceDto;
    }

    /**
     * 获取用户博客子空间列表
     * @param userId     用户主键
     * @param parentPath 父级空间路径
     * @return 博客子空间列表
     */
    private List<BlogSpaceEntity> getChildrenList(Long userId, String parentPath) {

        LambdaQueryWrapper<BlogSpaceEntity> blogSpaceLambdaQueryWrapper = new LambdaQueryWrapper<>();
        // 查询字段
        blogSpaceLambdaQueryWrapper.select(BlogSpaceEntity::getId, BlogSpaceEntity::getParentId, BlogSpaceEntity::getParentPath,
                BlogSpaceEntity::getName, BlogSpaceEntity::getSort, BlogSpaceEntity::getStatus);
        // 匹配条件
        blogSpaceLambdaQueryWrapper.eq(BlogSpaceEntity::getUserId, userId)
                .likeRight(BlogSpaceEntity::getParentPath, parentPath)
                .eq(BlogSpaceEntity::getDeleteStatus, CommonEnum.DELETE_NO.getValue());
        // 查询数据
        return baseMapper.selectList(blogSpaceLambdaQueryWrapper);
    }
}